﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Services.Client;
using System.Net;

namespace Wheels.TransitODataService
{
    public partial class TransitData
    {
        partial void OnContextCreated()
        {
            SendingRequest += OnSendingRequest;
        }

        void OnSendingRequest(object sender, SendingRequestEventArgs e)
        {
            var request = (HttpWebRequest)e.Request;
            request.Headers.Add("api_key", "M8xudPElsU2Gwe87MzYKVg");
        }

        private static string DecimalAsParam(decimal source)
        {
            // in case 0 in the end, odata service is not working
            // http://stackoverflow.com/questions/2109494/c-how-to-remove-0-from-the-end-of-a-decimal-value
            // in case string value is to long, odata service is not working
            return decimal.Round(source, 6).ToString("G29");
        }

        private static string DateTimeAsParam(DateTime source)
        {
            //return string.Format("datetime'{0}'",source.ToString("u"));
            return string.Format("datetime'{0}'", source.ToString("yyyy-MM-ddTHH:mm:ssZ"));
            
        }

        public Stop GetStop(string stopId, bool expandArrivals, bool expandSchedules, bool expandRoutes)
        {
            string uriString = string.Format("/Stops('{0}')", stopId);

            Uri uri = new Uri(uriString, UriKind.Relative);
            Stop stop = this.Execute<Stop>(uri).FirstOrDefault();


            if (expandArrivals)
            {
                this.LoadProperty(stop,"Arrivals");
            }
            
            if (expandSchedules)
            {
                this.LoadProperty(stop, "Schedule");
            }

            if (expandRoutes)
            {
                this.LoadProperty(stop, "Routes");
            }

            return stop;
        }

        //public IEnumerable<Arrival> GetArrivalsByStop(string stopId)
        //{            
        //    string uriString = string.Format("/Stops('{0}')/Arrivals", stopId);
        //    Uri uri = new Uri(uriString, UriKind.Relative);
        //    return this.Execute<Arrival>(uri);

        //    //http://localhost:62081/TransitODataService.svc/GetArrivalsByStop?stopId='3358'&arrivalCount=2147483647&includeArrivalTime=1&includeScheduleTime=1&from=&to=&api_key=M8xudPElsU2Gwe87MzYKVg
        //    //string uriString = string.Format("/GetArrivalsByStop()?stopId='{0}'&arrivalCount={1}&includeArrivalTime={2}&includeScheduleTime={3}&from={4}&to={5}",
        //    //    stopId,
        //    //    arrivalCount.ToString(),
        //    //    includeArrivalTime ? '1' : '0',
        //    //    includeScheduleTime ? '1' : '0',
        //    //    (from.HasValue) ? DateTimeAsParam(from.Value) : string.Empty,
        //    //    (to.HasValue) ? DateTimeAsParam(to.Value) : string.Empty
        //    //    );

        //    //Uri uri = new Uri(uriString, UriKind.Relative);
        //    //return this.Execute<Arrival>(uri);
        //}
        

        public IEnumerable<Stop> GetStopsAround(decimal latitude, decimal longitude, decimal areaSize)
        {
            //http://localhost:62081/TransitODataService.svc/GeoAreas('38,866759|-77,054161|0,01')/Stops?api_key=M8xudPElsU2Gwe87MzYKVg

            string uriString = string.Format("/GeoAreas('{0}|{1}|{2}')/Stops",
                DecimalAsParam(latitude),
                DecimalAsParam(longitude),
                DecimalAsParam(areaSize)
                );

            Uri uri = new Uri(uriString, UriKind.Relative);
            return this.Execute<Stop>(uri);            
        }

        public IEnumerable<Stop> GetStopsInArea(decimal latitude1, decimal longitude1, decimal latitude2, decimal longitude2)
        {
            //http://localhost:62081/TransitODataService.svc/GeoAreas('38,856204|-77,064710|38,877302|-77,043612')/Stops?api_key=M8xudPElsU2Gwe87MzYKVg

            string uriString = string.Format("/GeoAreas('{0}|{1}|{2}|{3}')/Stops",
                DecimalAsParam(latitude1),
                DecimalAsParam(longitude1),
                DecimalAsParam(latitude2),
                DecimalAsParam(longitude2)
                );

            Uri uri = new Uri(uriString, UriKind.Relative);
            return this.Execute<Stop>(uri);
        }

        public List<Itinerary> CalculateItineraryByStops(string stop1Id, string stop2Id, DateTime? startTime)
        {
            string uriString = string.Format("/CalculateItineraryByStops()?stop1Id='{0}'&stop2Id='{1}'&startTime={2}",
                stop1Id,
                stop2Id,
                (startTime.HasValue) ? DateTimeAsParam(startTime.Value) : string.Empty);

            Uri uri = new Uri(uriString, UriKind.Relative);
            List<Itinerary> result = this.Execute<Itinerary>(uri).ToList();
            result.ForEach(i =>
                {                    
                    this.LoadProperty(i, "Legs");
                }
                );
            return result;
        }

        public List<Itinerary> CalculateItineraryByPoints(double lat1, double lon1, double lat2, double lon2, DateTime? startTime)
        {
            string uriString = string.Format("/CalculateItineraryByPoints()?lat1={0}&lon1={1}&lat2={2}&lon2={3}&&startTime={4}",
                DecimalAsParam((decimal)lat1),
                DecimalAsParam((decimal)lon1),
                DecimalAsParam((decimal)lat2),
                DecimalAsParam((decimal)lon2),
                (startTime.HasValue) ? DateTimeAsParam(startTime.Value) : string.Empty);
            Uri uri = new Uri(uriString, UriKind.Relative);
            List<Itinerary> result = this.Execute<Itinerary>(uri).ToList();
            result.ForEach(i =>
            {
                this.LoadProperty(i, "Legs");
            }
                );
            return result;            
        }

    }
}